/*
 * To change this template, choose Tools | Templates
 * and open the template in the editor.
 */
package com.playground.client.websockets.application.boardgame;

import com.playground.client.websockets.entity.message.response.CheckersMakeMoveResponseMessage;
import com.playground.client.websockets.entity.message.response.CheckersYourTurnResponseMessage;
import com.playground.client.websockets.socket.PlayerSocket;
import com.playground.client.websockets.util.JsonUtil;
import com.playground.core.entity.Game;
import com.playground.core.entity.LoggedPlayer;
import com.playground.core.entity.Player;
import com.playground.core.entity.boardgame.BoardGame;
import com.playground.core.entity.boardgame.Move;
import com.playground.core.entity.boardgame.chesslikegame.ChessLikeSquare;
import com.playground.core.entity.boardgame.chesslikegame.checkers.CheckersPiece;
import com.playground.core.repository.RoomRepository;
import com.playground.core.service.LoginService;
import com.playground.core.service.factory.GameFactory;
import com.playground.core.service.ruler.CheckersRuler;
import com.sun.grizzly.tcp.Request;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.logging.Level;
import java.util.logging.Logger;

/**
 *
 * @author Tiago Peres
 */
public class CheckersApplication extends BoardGameApplication{
    private GameFactory gameFactory;
    private CheckersRuler checkersRuler;
    
    public CheckersApplication(LoginService loginService, RoomRepository roomRepository, GameFactory gameFactory, CheckersRuler checkersRuler){
        super(loginService, roomRepository);
        this.gameFactory = gameFactory;
        this.checkersRuler = checkersRuler;
    }

    @Override
    protected void giveUp(PlayerSocket socket) {
        throw new UnsupportedOperationException("Not supported yet."); //To change body of generated methods, choose Tools | Templates.
    }

    @Override
    public boolean isApplicationRequest(Request rqst) {
        return rqst.requestURI().toString().endsWith("/checkers");
    }

    @Override
    protected Game makeGame(List<LoggedPlayer> players) {
        return gameFactory.createCheckers(players);
    }

    @Override
    protected void informTurn(PlayerSocket socket) {
        System.out.println("Informing player turn");
        try{
        CheckersYourTurnResponseMessage response = new CheckersYourTurnResponseMessage();
        response.setSuccess(true);
        BoardGame game = (BoardGame) socket.getPlayer().getRoom().getGame();
        Map<CheckersPiece, List<ChessLikeSquare>> movable = checkersRuler.getAllowedPieces(game, socket.getPlayer());
        Map<Integer, List<Integer>> movableResponse = new HashMap<Integer, List<Integer>>();
        System.out.println(movable.keySet().size());
        for (CheckersPiece p : movable.keySet()){
            ArrayList<Integer> movableTo = new ArrayList<Integer>();
            for (ChessLikeSquare s : movable.get(p)){
                movableTo.add(s.getPosition());
            }
            movableResponse.put(p.getSquare().getPosition(), movableTo);
        }
        response.setMovablePieces(movableResponse);
        System.out.println(response.getMovablePieces().size());
        Logger.getLogger(CheckersApplication.class.getName()).log(Level.INFO, "about to write json");
        String json = JsonUtil.getGson().toJson(response, CheckersYourTurnResponseMessage.class);
        Logger.getLogger(CheckersApplication.class.getName()).log(Level.INFO, "arrived here");
        Logger.getLogger(CheckersApplication.class.getName()).log(Level.INFO, json);
        socket.send(json);
        } catch(Exception e){
            e.printStackTrace();
        }
    }

    @Override
    protected void executeMove(PlayerSocket socket, Move move) {
        BoardGame game = (BoardGame) socket.getPlayer().getRoom().getGame();
        Player madeTheMove = game.getPlayerInTurn();
        CheckersMakeMoveResponseMessage msg = new CheckersMakeMoveResponseMessage();
        Logger.getLogger(CheckersApplication.class.getName()).log(Level.INFO, "before test...");
        Logger.getLogger(CheckersApplication.class.getName()).log(Level.INFO, "src square: (" + ((ChessLikeSquare) move.getSource()).getRow() + ", " + ((ChessLikeSquare) move.getSource()).getColumn() + ")");
        Logger.getLogger(CheckersApplication.class.getName()).log(Level.INFO, "dest square: (" + ((ChessLikeSquare) move.getDestination()).getRow() + ", " + ((ChessLikeSquare) move.getDestination()).getColumn() + ")");
        if (checkersRuler.executeMove(game, move)){
            Logger.getLogger(CheckersApplication.class.getName()).log(Level.INFO, "move made, inside test...");
            msg.setPlayerId(madeTheMove.getId());
            Logger.getLogger(CheckersApplication.class.getName()).log(Level.INFO, "playerid was set");
            msg.setGameOver(checkersRuler.isGameOver(game));
            Logger.getLogger(CheckersApplication.class.getName()).log(Level.INFO, "gameover was set");
            msg.setKinged(((CheckersPiece) move.getDestination().getPiece()).isKinged());
            Logger.getLogger(CheckersApplication.class.getName()).log(Level.INFO, "kinged was set");
            msg.setSourceSquarePosition(move.getSource().getPosition());
            Logger.getLogger(CheckersApplication.class.getName()).log(Level.INFO, "srcsquare was set");
            msg.setDestinationSquarePosition(move.getDestination().getPosition());
            Logger.getLogger(CheckersApplication.class.getName()).log(Level.INFO, "destsquare was set");
            msg.setPlayerInTurnId(game.getPlayerInTurn().getId());
            Logger.getLogger(CheckersApplication.class.getName()).log(Level.INFO, "playerinturn was set");
            // look for removed pieces
            ChessLikeSquare src = (ChessLikeSquare) move.getSource();
            ChessLikeSquare dest = (ChessLikeSquare) move.getDestination();
            int difRow = dest.getRow() - src.getRow();
            int difCol = dest.getColumn() - src.getColumn();
            if (Math.abs(difRow) == 2){
                int removedRow = src.getRow() + difRow / 2;
                int removedCol = src.getColumn() + difCol / 2;
                int removedPosition = removedRow * 8 + removedCol;
                msg.setRemoved(removedPosition);
            }
            Logger.getLogger(CheckersApplication.class.getName()).log(Level.INFO, "removedpieces was set");
            msg.setSuccess(true);
            Logger.getLogger(CheckersApplication.class.getName()).log(Level.INFO, "success was set");
            msg.setWinnerId((null == game.getWinner()) ? null : game.getWinner().getId());
            Logger.getLogger(CheckersApplication.class.getName()).log(Level.INFO, "winner was set");
        } else{
            msg.setSuccess(false);
        }
        Logger.getLogger(CheckersApplication.class.getName()).log(Level.INFO, "everything was set. sending message...");
        Logger.getLogger(CheckersApplication.class.getName()).log(Level.INFO, "message: " + JsonUtil.getGson().toJson(msg, CheckersMakeMoveResponseMessage.class));
        sendToAll(socket.getPlayer().getRoom(), JsonUtil.getGson().toJson(msg, CheckersMakeMoveResponseMessage.class));
        informTurn(getPlayerSocketByPlayerId(game.getPlayerInTurn().getId()));
    }
    
}
